﻿Ext.extend(NExt.form.MoneyField, Ext.form.TextField, {
    fieldClass: "x-form-field x-form-num-field",

    allowDecimals: true,

    decimalSeparator: ".",

    groupSeparator: ",",

    mixSepators: false,

    decimalPrecision: 2,

    allowNegative: true,

    minValue: Number.NEGATIVE_INFINITY,

    maxValue: Number.MAX_VALUE,

    minText: "The minimum value for this field is {0}",

    maxText: "The maximum value for this field is {0}",

    nanText: "{0} is not a valid number",

    baseChars: "0123456789",

    style: 'text-align: right',

    // private
    initEvents: function() {
        var allowed = this.baseChars + this.groupSeparator;
        if (this.allowDecimals) {
            allowed += this.decimalSeparator;
        }
        if (this.allowNegative) {
            allowed += '-';
        }
        this.maskRe = new RegExp('[' + Ext.escapeRe(allowed) + ']');
        NExt.form.MoneyField.superclass.initEvents.call(this);
    },

    // private
    validateValue: function(value) {
        if (!NExt.form.MoneyField.superclass.validateValue.call(this, value)) {
            return false;
        }
        if (value.length < 1) { // if it's blank and textfield didn't flag it then it's valid
            return true;
        }
        var v = this.removeSeparators(value);
        if (isNaN(v)) {
            this.markInvalid(String.format(this.nanText, v));
            return false;
        }
        var num = this.parseValue(value);
        if (num < this.minValue) {
            this.markInvalid(String.format(this.minText, this.minValue));
            return false;
        }
        if (num > this.maxValue) {
            this.markInvalid(String.format(this.maxText, this.maxValue));
            return false;
        }
        return true;
    },

    getValue: function() {
        return this.fixPrecision(this.parseValue(NExt.form.MoneyField.superclass.getValue.call(this)));
    },

    getModel: function() {
        var model = this.getValue();
        return model;
    },

    setValue: function(v) {
        v = typeof v == 'number' ? v : parseFloat(this.removeSeparators(v));
        v = isNaN(v) ? '' : this.formatMoney(v);
        return NExt.form.MoneyField.superclass.setValue.call(this, v);
    },

    setModel: function(model) {
        this.setValue(model);
    },

    // private
    parseValue: function(value) {
        value = parseFloat(this.removeSeparators(value));
        return isNaN(value) ? '' : value;
    },

    // private
    removeSeparators: function(value) {
        var regex = new RegExp(this.groupSeparator, 'g');
        return String(value).replace(regex, '').replace(this.decimalSeparator, '.');
    },

    replaceGroupSeparator: function(value, ch) {
        var regex = new RegExp(this.groupSeparator, 'g');
        var v = String(value).replace(regex, ch);
        return v;
    },

    // private
    fixPrecision: function(value) {
        var nan = isNaN(value);
        if (!this.allowDecimals || this.decimalPrecision == -1 || nan || !value) {
            return nan ? '' : value;
        }
        return parseFloat(parseFloat(value).toFixed(this.decimalPrecision));
    },

    // private
    formatMoney: function(value) {
        value = this.removeSeparators(value);
        if (isNaN(value))
            return '';

        var precision, isPositive, nextGroupPosition, cents, missingDigits;
        precision = Math.pow(10, this.decimalPrecision);
        isPositive = (value == (value = Math.abs(value)));
        value = Math.floor(value * precision + 0.50000000001);
        cents = value % precision;
        missingDigits = this.decimalPrecision - String(cents).length;
        for (var i = 0; i < missingDigits; i++) {
            cents = '0' + cents;
        }

        value = Math.floor(value / precision).toString();
        for (var i = 0; i < Math.floor((value.length - (1 + i)) / 3); i++) {
            nextGroupPosition = (4 * i + 3);
            value = value.substring(0, value.length - nextGroupPosition) + this.groupSeparator + value.substring(value.length - nextGroupPosition);
        }

        return (((isPositive) ? '' : '-') + value + this.decimalSeparator + cents);
    },

    beforeBlur: function() {
        var v = this.getRawValue();
        if (this.mixSepators) {
            v = this.replaceGroupSeparator(v, this.decimalSeparator);
        }
        v = this.parseValue(v);
        if (!Ext.isEmpty(v)) {
            this.setValue(this.fixPrecision(v));
        }
    },

    preFocus: function() {
        if (this.mixSepators) {
            var v = this.replaceGroupSeparator(this.getRawValue(), '');
            NExt.form.MoneyField.superclass.setValue.call(this, v);
        }
        NExt.form.MoneyField.superclass.preFocus.call(this);
    },

    //patch ie7 keyChar problem
    //http://www.extjs.com/forum/showthread.php?t=8700
    filterKeys: function(e) {
        var k = e.getKey();
        if (!Ext.isIE && (e.isNavKeyPress() || k == e.BACKSPACE || (k == e.DELETE && e.button == -1))) {
            return;
        }
        if (Ext.isIE && (k == e.BACKSPACE || k == e.DELETE || e.isNavKeyPress() || k == e.HOME || k == e.END)) {
            return;
        }
        var c = e.getCharCode();
        if (!this.maskRe.test(String.fromCharCode(c) || '')) {
            e.stopEvent();
        }
    }
});